/**
 * @file Transaction.h
 * @brief 定义数据库事务相关的类和枚举
 * @details 提供事务管理、事务隔离级别控制和嵌套事务支持
 */

#pragma once

#include "ConnectionPool.h"
#include "DatabaseError.h"
#include <memory>
#include <stack>

namespace CLink
{
namespace Db
{

/**
 * @brief 事务隔离级别枚举
 * @details 定义数据库事务的四种标准隔离级别
 */
enum class IsolationLevel
{
    READ_UNCOMMITTED,  ///< 读未提交：允许脏读，一个事务可以读取另一个事务未提交的数据
    READ_COMMITTED,    ///< 读已提交：防止脏读，一个事务只能读取另一个事务已提交的数据
    REPEATABLE_READ,   ///< 可重复读：在一个事务中多次读取同一数据时，结果保持一致
    SERIALIZABLE       ///< 串行化：最高隔离级别，完全串行执行事务，防止所有并发问题
};

/**
 * @brief 事务状态枚举
 * @details 表示事务的当前状态
 */
enum class TransactionState
{
    ACTIVE,       ///< 事务处于活动状态
    COMMITTED,    ///< 事务已提交
    ROLLED_BACK   ///< 事务已回滚
};

/**
 * @brief 事务类
 * @details 管理数据库事务的开始、提交和回滚操作
 */
class CLINK_CLASS Transaction
{
public:
    /**
     * @brief 构造函数，创建并开始一个新事务
     * @param connection 数据库连接指针
     * @param level 事务隔离级别，默认为可重复读
     */
    explicit Transaction(ConnectionPool::ConnectionPtr connection, IsolationLevel level = IsolationLevel::REPEATABLE_READ);
    
    /**
     * @brief 禁用拷贝构造函数
     */
    Transaction(const Transaction &) = delete;
    
    /**
     * @brief 禁用拷贝赋值运算符
     */
    Transaction &operator=(const Transaction &) = delete;
    
    /**
     * @brief 析构函数，如果事务仍处于活动状态则回滚
     */
    ~Transaction();

    /**
     * @brief 提交事务
     * @throws DatabaseError 如果事务已经提交或回滚
     */
    void commit();
    
    /**
     * @brief 回滚事务
     * @throws DatabaseError 如果事务已经提交或回滚
     */
    void rollback();
    
    /**
     * @brief 获取事务当前状态
     * @return 事务状态
     */
    TransactionState getState() const;
    
private:
    /**
     * @brief 开始事务
     */
    void begin();
    
    /**
     * @brief 设置事务隔离级别
     */
    void setIsolationLevel();

    ConnectionPool::ConnectionPtr _connection;  ///< 数据库连接指针
    TransactionState _state;                    ///< 事务当前状态
    IsolationLevel _level;                      ///< 事务隔离级别
};

/**
 * @brief RAII风格的事务包装器
 * @details 自动管理事务的生命周期，确保事务在作用域结束时被正确处理
 */
class CLINK_CLASS TransactionGuard
{
public:
    /**
     * @brief 构造函数，接管事务的管理
     * @param transaction 要管理的事务对象
     */
    explicit TransactionGuard(Transaction &transaction);
    
    /**
     * @brief 析构函数，确保事务被正确处理
     */
    ~TransactionGuard();

    /**
     * @brief 禁用拷贝构造函数
     */
    TransactionGuard(const TransactionGuard &) = delete;
    
    /**
     * @brief 禁用拷贝赋值运算符
     */
    TransactionGuard &operator=(const TransactionGuard &) = delete;
    
    /**
     * @brief 禁用移动构造函数
     */
    TransactionGuard(TransactionGuard &&) = delete;
    
    /**
     * @brief 禁用移动赋值运算符
     */
    TransactionGuard &operator=(TransactionGuard &&) = delete;

private:
    Transaction &_transaction;  ///< 引用的事务对象
};

/**
 * @brief 嵌套事务支持类
 * @details 通过数据库保存点(savepoint)机制实现嵌套事务，允许在主事务内创建子事务
 */
class CLINK_CLASS NestedTransaction
{
public:
    /**
     * @brief 构造函数，创建一个嵌套事务
     * @param connection 数据库连接指针
     */
    explicit NestedTransaction(ConnectionPool::ConnectionPtr connection);
    
    /**
     * @brief 析构函数，如果嵌套事务仍处于活动状态则回滚
     */
    ~NestedTransaction();

    /**
     * @brief 提交嵌套事务
     * @throws DatabaseError 如果嵌套事务已经提交或回滚
     */
    void commit();
    
    /**
     * @brief 回滚嵌套事务
     * @throws DatabaseError 如果嵌套事务已经提交或回滚
     */
    void rollback();

private:
    ConnectionPool::ConnectionPtr _connection;  ///< 数据库连接指针
    std::string _savepointName;                 ///< 保存点名称
    bool _active = true;                        ///< 标记嵌套事务是否处于活动状态
    static std::atomic<uint64_t> _savepointCounter;  ///< 用于生成唯一保存点名称的计数器
};
} // namespace db
} // namespace CLink